#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include "ProceduralSystem/ProceduralProductionRuleBaseSimple.h"

void CProceduralProductionRuleBaseSimple::CalcSize()
{
}

CProceduralModule* CProceduralProductionRuleBaseSimple::GenerateModule(int nX,int nY)
{
	CProceduralModule *module=0;
	// get the surrounding modules
	// if nothing, starts placing a corner

	// example: 1,0 -> corner
	// 1) you look at the links from corner module
	// 2) see the connected one
	// 3) displace a new one

	return module;

}
//////////////////////////////////////////////////////////////////////////

void CProceduralProductionRuleBaseSimple::GenerateFloor(TModulesList &modulesList)
{
	if (modulesList.empty()) 
		return;

	CProceduralProductionUtils procUtils;

	// Get random value
	int startModuleNo = rand() % (modulesList.size()); // random module number for the start

	TModulesList generatedModulesList; // list of modules to generate

	// add first element to start from some random place on this floor
	generatedModulesList.push_back(modulesList[startModuleNo]);

	// final list of created modules
	TModulesList currentFloorList;

	for (int generatedModulesNo=0; generatedModulesNo < generatedModulesList.size(); ++generatedModulesNo)
	{
		CProceduralModule &mainModule = generatedModulesList[generatedModulesNo];

		if (!mainModule.m_pObject)
			continue;

		// Add main module if not in the currentFloorList list yet or it is the starting main module
		if ( (!IsModuleInModulesList(generatedModulesList,generatedModulesList[generatedModulesNo])) || generatedModulesNo == 0 )
		{
			CProceduralModule newMainModule;
			currentFloorList.push_back(SpawnModule(mainModule, newMainModule, mainModule.m_pObject->GetWorldPos()));		
		}

		// Iterate through available directions and create links if found
		for (int linkNo=0; linkNo<generatedModulesList[generatedModulesNo].m_Links.size(); ++linkNo)
		{
			CProceduralModuleLink linkedModule = generatedModulesList[generatedModulesNo].m_Links[linkNo];

			if (!IsModuleInModulesList(generatedModulesList,*linkedModule.m_pLink)) // if does not exist in the created objects list
			{
				Vec3 newModulePos = generatedModulesList[generatedModulesNo].m_pObject->GetWorldPos() + linkedModule.m_vDisplacement;			

				CProceduralModule newLinkModule;
				currentFloorList.push_back(SpawnModule(*linkedModule.m_pLink,newLinkModule, newModulePos));
				generatedModulesList.push_back(*linkedModule.m_pLink);
			};			
		}

	} // End of building creation


	// Get the currently selected building
	if (!CProcSettings::GetProcSettings().buildingSelected)
		return;
	CPrefabBuildingObject *building = (CPrefabBuildingObject*) GetIEditor()->GetObjectManager()->FindObject(CProcSettings::GetProcSettings().lastBuildingGUID);
	if (!building)
		return;

	//Add new objects without re-creating the prefab each time.
	for ( TModulesListIt sIter = currentFloorList.begin() ; sIter!= currentFloorList.end(); ++sIter)
	{
		CProceduralModule *currentProcModule = &(*sIter);
		CBaseObject *currentObject =  currentProcModule->m_pObject;
		building->AddObjectToPrefab(currentObject,true);
	}
}

void CProceduralProductionRuleBaseSimple::AddModuleLinks(TModulesList &modulesList)
{
	CProceduralProductionUtils procUtils;

	for (TModulesListIt i1=modulesList.begin(); i1!=modulesList.end();++i1)		
	{	
		CProceduralModule &pModule1=*i1;

		const Vec3 vModuleCenter1 = pModule1.m_bbox.GetCenter();

		Vec3 vModuleMin1 = pModule1.m_bbox.min;			
		Vec3 vModuleMax1 = pModule1.m_bbox.max;			

		vModuleMin1.z=vModuleMax1.z=0;
		float fMaxExtentSquare=vModuleMin1.GetSquaredDistance(vModuleMax1);

		// Iterate through modules
		// Pick second module and add as a link of first module if in defined distance range
		for (TModulesListIt i2=modulesList.begin(); i2!= modulesList.end();++i2)		
		{
			// skip the same object
			if (i1==i2)
				continue;

			CProceduralModule &pModule2=*i2;

			float fDist2=procUtils.GetBBoxSquareDistance(pModule2.m_bbox,vModuleCenter1);

			if (fDist2<fMaxExtentSquare)
			{
				CProceduralModuleLink newLink;
				Vec3 vDisp = pModule2.m_pObject->GetPos()-pModule1.m_pObject->GetPos();
				newLink.m_pLink=&pModule2;
				newLink.m_vDisplacement = vDisp;
				pModule1.m_Links.push_back(newLink);
			}				
		}
	}
}